package main

import (
	"fmt"
	"unsafe"
)

//面向对象的三个基本特征:1，封装2，继承3，多态4，方法重载4，抽象基类
//定义struct go语言没有class这个概念所以说对于很多人来说会少理解很多面向对象抽象的概念
//结构体大小写敏感 访问权限更改  小写类似于privt  大写类似于public
type Course struct {
	Name  string
	Price int
	Url   string
}

//函数的接收者
func (c Course) printCourseInfo() {
	fmt.Printf("课程名：%s，课程价格：%d，课程的地址：%s", c.Name, c.Price, c.Url)
}
func (c *Course) setPrice(price int) {
	(*c).Price = price
}

func main() {

	var c Course = Course{
		Name:  "django",
		Price: 100,
		Url:   "https://www.baidu.com",
	}
	fmt.Println(c.Name, c.Url, c.Price)
	//顺序形式
	c2 := Course{"scrapy", 110, "https://www.baidu.com"}
	fmt.Println(c2.Name, c2.Url, c2.Price)
	//如果一个指向结构体的指针
	c3 := &Course{"tornado", 110, "https://www.baidu.com"}
	//fmt.Printf("%T", c3)
	//fmt.Println((*c3).Name, (*c3).Url, (*c3).Price)
	//这里其实是go语言的一个语法糖 go语言内部会将c3转换成(*c3) go语言实际上在借鉴动态语言的特性
	fmt.Println(c3.Name, c3.Url, c3.Price)
	//零值化
	c4 := Course{}
	println(c4.Name)
	//	多种零值化
	var c5 Course = Course{}
	var c6 Course
	//var c7 *Course = new(Course)
	var c7 *Course = &Course{}
	//指针如果只申明不赋值默认值是nil c6不是指针是结构体的类型
	fmt.Println("零值初始化")
	fmt.Println(c5.Price)
	fmt.Println(c6.Price)
	fmt.Println(c7.Price)
	//	结构体是值类型
	c8 := Course{"scrapy", 110, "https://www.baidu.com"}
	c9 := c8
	fmt.Println(c8)
	fmt.Println(c9)
	c8.Price = 200
	fmt.Println(c8)
	fmt.Println(c9)
	//结构体的大小  占用内存的大小 可以使用sizeof类查看对象占用的类型
	//go语言string的本质其实string是一个结构体  这里也就是结构体的内存占用
	fmt.Println(unsafe.Sizeof(1))

	fmt.Println(unsafe.Sizeof("scrapy-django-"))
	//	slice 大小 24个字节
	/*type slice struct{
		array unsafe.Pointer//底层数组地址
		len int //长度
		cap int //容量
	}*/
	s1 := []string{"django", "tornado", "scrapy", "celery", "snaic", "flask"}
	fmt.Println("切片占用的内存:", unsafe.Sizeof(s1))
	m1 := map[string]string{
		"bobby1": "django",
		"bobby2": "tornado",
		"bobby3": "scrapy",
	}
	fmt.Println(unsafe.Sizeof(m1))

	//	结构体方法 达到了封装数据和封装方法的效果
	c10 := Course{"scrapy", 110, "https://www.baidu.com"}
	(&c10).setPrice(200)
	//Course.printCourseInfo(c10)
	c10.printCourseInfo()

}
